<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of PDOAbstract
 *
 * @author agama
 */
namespace org\copperforest\oak\sql;

class PDO extends \PDO
{

    //put your code here
    public $helper;
    protected $engine;
    protected $engines;
    protected $catalog;
    protected $schema;
    protected $prepareGetLock = null;
    protected $prepareReleaseLock = null;
    protected $locks = array( );

    function __construct( $dsn, $username, $passwd, $options )
    {

        parent::__construct( $dsn, $username, $passwd, $options );
        
        $matches = array( );
        if ( preg_match( '/^([a-z]+):/', $dsn, $matches ) ) {

            $this->engine = $matches[ 1 ];
            $this->helper = new SQLEngineHelper( $this->engine );
            
            //list( $this->catalog, $this->schema ) = $this->helper->getCatalogAndSchema( $dsn );
            $matches = array( );
            if ( preg_match( '/[;:]dbname=([^;]+)($|;)/', $dsn, $matches ) ){
                
                if( $this->engine == 'mysql' ){
                    
                    $this->catalog = 'def';
                    $this->schema = $matches[ 1 ];
                }
                else if( $this->engine == 'mssql'){
                    $this->catalog = $matches[ 1 ];
                }   
            }
        }
    }

    function getHelper()
    {
        return $this->helper;
    }
    
    function getEngine()
    {
        return $this->engine;
    }
    
    function getStorageEngines()
    {
        if( empty( $this->engines ) ){
            
            $stmnt = $this->prepare( $this->helper->getStorageEnginesSQL() );
            $stmnt->execute();

            $this->engines = array();
            while( $engine= $stmnt->fetchColumn () ) {
                $this->engines[] = $engine;
            }
            
        }
        
        return $this->engines;
    }
    
    function getSchema()
    {
        
        if( empty( $this->schema ) ){
            
            if( $this->engine == 'mssql' ){
                $result = $link->query( $this->helper->getDefaultSchemaSQL() );
                list( $this->schema, ) = $result->fetch( \PDO::FETCH_NUM );
                $result->closeCursor();
            }
        }
        
        return $this->schema;
    }
    
    function getCatalog()
    {
        return $this->catalog;
    }

    function getLock( $token, $time )
    {

        $this->locks[ $token ] = true;

        switch ( $this->engine ) {
            case 'mssql':

                if ( $this->prepareGetLock === null ) {
                    $sql = 'DECLARE @result int;';
                    $sql .= 'EXEC @result = sp_getapplock @Resource = ?, @LockMode = \'Exclusive\',  @LockTimeout=?;';
                    $sql .= 'SELECT CASE @result WHEN 0 THEN 1 WHEN 1 THEN 1 ELSE 0 END;';

                    $this->prepareGetLock = $this->prepare( $sql );
                }

                $result = null;
                $this->prepareGetLock->bindParam( 1, $token, \PDO::PARAM_STR );
                $this->prepareGetLock->bindParam( 2, $time, \PDO::PARAM_INT );
                $this->prepareGetLock->bindColumn( 1, $result );
                $this->prepareGetLock->execute();

                return $result;

            case 'mysql':
                $stmt = $this->query( 'SELECT GET_LOCK(' . $this->quote( $token ) . ',' . $time . ')' );
                $result = $stmt->fetchColumn( 0 );
                $stmt->closeCursor();

                return $result;
        }
    }

    function releaseLock( $token )
    {
        $result = null;


        switch ( $this->engine ) {
            case 'mssql':
                if ( $this->prepareReleaseLock === null ) {
                    $sql = 'EXEC @result = sp_releaseapplock  @Resource = ?';
                    $sql .= 'SELECT CASE @result WHEN 0 THEN 1 WHEN 1 THEN 1 ELSE 0 END;';
                    $this->prepareReleaseLock = $this->prepare( $sql );
                }


                $this->prepareReleaseLock->bindParam( 1, $token, PDO::PARAM_STR );
                $this->prepareReleaseLock->bindColumn( 1, $result );
                $this->prepareReleaseLock->execute();
                break;

            case 'mysql':
                $stmt = $this->query( 'DO RELEASE_LOCK(' . $this->quote( $token ) . ')' );
               // $result = $stmt->fetchColumn( 1 );
                $stmt->closeCursor();
                break;
        }

        if ( $result ) unset( $this->locks[ $token ] );


        return $result;
    }

    /*
      // 'WITH (ROWLOCK , READCOMMITTED)';//para cada tabla que quiera bloquear
      //
      //
      //

    /*
      static function _release_locks(){
      foreach($this->locks as $token=>$true)
      $this->releaseLock($token);
      }
     */

    function __destruct()
    {
        //self::_release_locks();

        foreach ( $this->locks as $token => $true )
                $this->releaseLock( $token );
    }

}

//register_shutdown_function(array('\org\copperforest\oak\sql\PDO','_release_locks'));
